package com.cmpe.group6.storyroad;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import android.app.Fragment;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.InflateException;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.cmpe.group6.storyroad.jsonClasses.MapPin;
import com.cmpe.group6.storyroad.jsonClasses.MapPinHolder;
import com.google.android.gms.common.GooglePlayServicesNotAvailableException;
import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.InfoWindowAdapter;
import com.google.android.gms.maps.GoogleMap.OnInfoWindowClickListener;
import com.google.android.gms.maps.MapView;
import com.google.android.gms.maps.MapsInitializer;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.gson.Gson;

/**
 * A simple {@link android.support.v4.app.Fragment} subclass. Activities that
 * contain this fragment must implement the
 * {@link FragmentMap.OnFragmentInteractionListener} interface to handle
 * interaction events. Use the {@link FragmentMap#newInstance} factory method to
 * create an instance of this fragment.
 * 
 */
public class FragmentMap extends Fragment {

	private static View view;
	private MapPin[] mapPins;
	private MapPinTask mTask;
	private MapView mapView;
	private GoogleMap googleMap;
	private ProgressBar progressBar;
	private ViewGroup infoWindow;
	private HashMap<Marker, String> markerStoryIdMap;

	public FragmentMap() {

	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		// Inflate the layout for this fragment

		if (view != null) {
			ViewGroup parent = (ViewGroup) view.getParent();
			if (parent != null)
				parent.removeView(view);
		}
		try {
			view = inflater.inflate(R.layout.fragment_map, container, false);
			mapView = (MapView) view.findViewById(R.id.mapview);
			progressBar = (ProgressBar) view.findViewById(R.id.progressBar_map);
			mapView.onCreate(savedInstanceState);
			mapView.onResume();// needed to get the map to display immediately

			try {
				MapsInitializer.initialize(getActivity());
			} catch (GooglePlayServicesNotAvailableException e) {
				e.printStackTrace();
			}
			googleMap = mapView.getMap();
			googleMap.getUiSettings().setMyLocationButtonEnabled(true);
			return view;
		} catch (InflateException e) {
			e.printStackTrace();
		}
		return view;

	}

	@Override
	public void onViewCreated(View view, Bundle savedInstanceState) {
		super.onViewCreated(view, savedInstanceState);
		Button createStoryButton = (Button) getView()
				.findViewById(R.id.button1);

		// Directs the user to create story page.
		createStoryButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				Intent createStory = new Intent(getActivity(),
						CreateStory.class);
				startActivity(createStory);

			}
		});

		mTask = new MapPinTask();
		mTask.execute((Void) null);

		// Clicking on a info window directs the user to that pin's story.
		googleMap.setOnInfoWindowClickListener(new OnInfoWindowClickListener() {

			@Override
			public void onInfoWindowClick(Marker arg0) {
				Intent readStoryIntent = new Intent(getActivity(),
						ReadStoryActivity.class);
				readStoryIntent.putExtra("story_id", markerStoryIdMap.get(arg0));
				startActivity(readStoryIntent);
			}
		});

		// Setting the default position of the map.
		LatLng coordinates = new LatLng(41.1, 29);
		CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(
				coordinates, 11);
		googleMap.animateCamera(cameraUpdate);

	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

	}

	/**
	 * Represents an asynchronous Map pin task to get all stories' coordinates
	 * from the server and creating pins for them.
	 * 
	 */
	public class MapPinTask extends AsyncTask<Void, Void, Boolean> {
		@Override
		protected void onPreExecute() {
			progressBar.setVisibility(View.VISIBLE);
		}

		@Override
		protected Boolean doInBackground(Void... params) {
			DefaultHttpClient httpclient = new DefaultHttpClient();
			HttpPost httppost = new HttpPost(Utils.SERVER_NAME + "GetMapPins");

			try {
				// Add your data
				List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(
						3);
				nameValuePairs.add(new BasicNameValuePair("request_type",
						"Android"));
				httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

				// Execute HTTP Post Request
				HttpResponse response = httpclient.execute(httppost);

				String jsonResponse = EntityUtils
						.toString(response.getEntity());
				Gson gson = new Gson();
				mapPins = gson.fromJson(jsonResponse, MapPinHolder.class).mapPins;

			} catch (ClientProtocolException e) {
				// TODO Auto-generated catch block
			} catch (IOException e) {
				// TODO Auto-generated catch block
			}

			return true;
		}
		
		/*
		 * (non-Javadoc)
		 * @see android.os.AsyncTask#onPostExecute(java.lang.Object)
		 */
		@Override
		protected void onPostExecute(final Boolean success) {

			if (!success) {
				Toast.makeText(getActivity(), "Connection Error",
						Toast.LENGTH_SHORT).show();
			} else {
				markerStoryIdMap = new HashMap<Marker, String>();
				infoWindow = (ViewGroup) (getActivity()).getLayoutInflater()
						.inflate(R.layout.list_item, null);
				googleMap.setInfoWindowAdapter(new InfoWindowAdapter() {

					@Override
					public View getInfoWindow(Marker arg0) {

						return null;
					}

					// Preparing info popups for markers.
					@Override
					public View getInfoContents(Marker arg0) {

						// set title
						((TextView) infoWindow.findViewById(R.id.title))
								.setText(arg0.getTitle());
						String rating;
						String tags = "";
						String[] temp = arg0.getSnippet().split("#");
						rating = temp[0];
						if (temp.length > 1) {
							tags = temp[1];
						}
						// set freeText
						((TextView) infoWindow.findViewById(R.id.desc_rating))
								.setText(rating);
						((TextView) infoWindow.findViewById(R.id.desc_tags))
								.setText(tags);

						return infoWindow;
					}
				});

				// Creating map markers for stories.
				for (int i = 0; i < mapPins.length; i++) {
					Marker marker = googleMap.addMarker(new MarkerOptions()
							.position(
									new LatLng(mapPins[i].getX_coord(),
											mapPins[i].getY_coord()))
							.draggable(false)
							.visible(true)
							.title((mapPins[i].getTitle()))
							.snippet(
									"Rating: " + mapPins[i].getRating()
											+ "#" + mapPins[i].getTags()));
					markerStoryIdMap.put(marker,
							String.valueOf(mapPins[i].getS_id()));
				}
			}
			progressBar.setVisibility(View.GONE);
		}

		@Override
		protected void onCancelled() {

		}
	}

	/*
	 * Using a mapview in a fragment requires you to 'route' the lifecycle
	 * events of the fragment to the mapview
	 */
	@Override
	public void onResume() {
		super.onResume();
		if (null != mapView)
			mapView.onResume();
	}

	@Override
	public void onPause() {
		super.onPause();
		if (null != mapView)
			mapView.onPause();
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		if (null != mapView)
			mapView.onDestroy();
	}

	@Override
	public void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);
		if (null != mapView)
			mapView.onSaveInstanceState(outState);
	}

	@Override
	public void onLowMemory() {
		super.onLowMemory();
		if (null != mapView)
			mapView.onLowMemory();
	}
}
